const { expect } = require("chai");
const { ethers } = require("hardhat");
const { loadFixture } = require("@nomicfoundation/hardhat-toolbox/network-helpers")

describe("Market Contract", async function () {
  const FEE = ethers.parseUnits("0.01", 18)
  async function deployFactoryFixture() {
    // 获取账户
    const [admin, user1, user2, user3] = await ethers.getSigners()

    // 部署Factory合约
    const Market = await ethers.getContractFactory("Market")
    const market = await Market.deploy(FEE)

    // 返回相关变量
    return { admin, user1, user2, user3, market }
  }

  async function createIssueFixture() {
    const { user1, market } = await loadFixture(deployFactoryFixture)
    const description = "Test issue"
    const options = ["Option 1", "Option 2"]
    //timestamp
    const deadline = Math.floor(Date.now() / 1000) + 3600
    await market.connect(user1).createIssue(description,options,deadline,{ value: FEE })
    const issue = await market.issues(0)
    return { issue }
  }

  // 部署合约
  it("Should deploy the contract", async function () {
    const { admin, user1, user2, user3, market } = await loadFixture(deployFactoryFixture)
    expect(await market.owner()).to.equal(admin.address)
    expect(await market.fee()).to.equal(FEE)
  })
  // 创建问题
  it("Should create an issue", async function () {
    const { admin, market } = await loadFixture(deployFactoryFixture)
    const description = "Test issue"
    const options = ["Option 1", "Option 2"]
    //timestamp
    const deadline = Math.floor(Date.now() / 1000) + 3600
    await market.connect(admin).createIssue(description,options,deadline,{ value: FEE })

    expect(await market.feePool() == FEE)
  })

  // 下注
  it("Should place a bet",async ()=>{
    const { admin, market } = await loadFixture(deployFactoryFixture)
    const {issue} = await loadFixture(createIssueFixture)
    const issueId = 0
    const optionId = 0
    const amount = ethers.parseUnits("0.1", 18)
    await market.connect(admin).placeBet(issueId,optionId,amount,{value:amount})

    expect(await market.connect(admin).getBet(issueId,optionId)).to.equal(amount)
    expect(await market.getOptionPool(issueId,optionId)).to.equal(amount)
    expect((await market.getIssue(issueId)).pool == (amount))
  })

  // 结算
  it("Should settle the issue",async ()=>{
    const { admin, market } = await loadFixture(deployFactoryFixture)
    await loadFixture(createIssueFixture)
    const issueId = 0
    const winningOptionId = 1
    const issue = await market.getIssue(issueId)
    market.connect(admin).resolveIssue(issue,winningOptionId)
    expect(issue.isResolved == true)
    expect(issue.winningOption == winningOptionId)
    //check total fee
    expect(await market.feePool() === BigInt(FEE) + BigInt(issue.pool) / BigInt(10));
  })

  // 领奖
  it("Should claim reward", async () => {
    const { admin, user1, user2, market } = await loadFixture(deployFactoryFixture);
    await loadFixture(createIssueFixture);

    const issueId = 0;
    const amount = ethers.parseUnits("0.1", 18);

    // 用户1和用户2分别下注
    await market.connect(user1).placeBet(issueId, 0, amount, { value: amount });
    await market.connect(user2).placeBet(issueId, 1, amount, { value: amount });

    // 临时移除时间限制用于测试
    await market.connect(admin).resolveIssue(issueId, 0);

    // 获取奖池金额
    const pool = (await market.getIssue(issueId)).pool;

    // 获取用户1的初始余额
    const user1InitialBalance = await ethers.provider.getBalance(user1.address);

    // 用户1领取奖励
    const tx = await market.connect(user1).claim(issueId);
    const receipt = await tx.wait(); // 获取交易回执
    const gasUsed = receipt.gasUsed; // 获取交易消耗的 Gas
    const gasPrice = tx.gasPrice; // 获取 Gas 价格
    const gasCost = gasUsed * gasPrice; // 计算 Gas 费用

    // 获取用户1的最终余额
    const user1FinalBalance = await ethers.provider.getBalance(user1.address);

    // 计算用户1的余额变化
    const balanceChange = user1FinalBalance - user1InitialBalance - gasCost;
    
    // 验证余额变化是否等于预期余额变化
    expect(balanceChange).to.be.closeTo(pool, ethers.parseUnits("0.001", 18)); // 允许 0.001 ETH 的误差
  });

});
